package com.hm.health.Activity;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.util.TypedValue;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ListView;
import android.widget.TextView;

import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;

import com.goodix.comsdk.RomaDevice;
import com.goodix.iot.libbase.utils.BluetoothUtil;
import com.goodix.iot.libcommounication.connection.IDeviceScanner;
import com.goodix.iot.libcommounication.connection.ble.BleDeviceScanner;
import com.goodix.iot.libcommounication.connection.spp.SppDeviceScanner;
import com.goodix.iot.libcommounication.connection.usb.UsbDeviceScanner;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.hm.health.MyApplication;
import com.hm.health.R;
import com.hm.health.adapter.LeDevicesAdapter;
import com.hm.health.entity.BleDevicesInfo;
import com.hm.health.widget.DeviceFilterPopWindow;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import rx.functions.Action1;

public class LeDeviceListActivity extends BaseActivity
        implements SwipeRefreshLayout.OnRefreshListener {
    private static final String TAG = LeDeviceListActivity.class.getSimpleName();

    public static final String ARG_IS_SINGLE_SELECTED = "ARG_IS_SINGLE_SELECTED";
    public static final String SELECTED_BLE_DEVICES = "SELECTED_BLE_DEVICES";
    public static final String ARG_BOUNDED_DEVICES = "ARG_BOUNDED_DEVICES";
    public static final int MSG_REFREH_DEVICE_SCAN_RESULT = 1;

    @BindView(R.id.lv_ble_devices)
    ListView mListViewBleDevices;
    @BindView(R.id.tv_start)
    TextView mTvStart;
    @BindView(R.id.swipeRefreshLayout)
    SwipeRefreshLayout mSwipeRefreshLayout;
    @BindView(R.id.tv_filter_info)
    TextView mTvFilterInfo;

    private Context mContext;
    private BleDeviceScanner mBleDeviceScanner;
    private ArrayList<BleDevicesInfo> mListBleDevices = new ArrayList<>();
    private LeDevicesAdapter mLeDeviceAdapter;
    private boolean mIsSingleSelected = false;
    ArrayList<BleDevicesInfo> mSelectedBleDevices = new ArrayList<>();
    private UsbDeviceScanner mUsbDeviceScanner;
    boolean mIsRefresing = false;
    private List<BleDevicesInfo> mBoundedDevices = new ArrayList<>();
    private int mMinRssi = -100;
    private String mNameFilter= "";
    private Map<String, BleDevicesInfo> mBuffer = new HashMap<>();
    private String mAddressFilter = "";
    private DeviceFilterPopWindow mPopWindow;
    private Menu mActionBar;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_le_device_list);
        ButterKnife.bind(this);
        MyApplication.getInstance().addActivity(this);
        mContext = this;
        mBleDeviceScanner = new BleDeviceScanner(getApplicationContext());
        mUsbDeviceScanner = new UsbDeviceScanner(getApplicationContext());
        mIsRefresing = true;

        Intent intent = getIntent();
        if (null != intent) {
            mIsSingleSelected = intent.getBooleanExtra(ARG_IS_SINGLE_SELECTED, false);
            String jsonStr = intent.getStringExtra(ARG_BOUNDED_DEVICES);
            if (null != jsonStr && !jsonStr.isEmpty()) {
                mBoundedDevices = new Gson().fromJson(jsonStr,
                        new TypeToken<List<BleDevicesInfo>>(){}.getType());
                BleDevicesInfo device = null;
                for (int i = 0; i < mBoundedDevices.size(); i++) {

                    device = mBoundedDevices.get(i);
                    Log.d(TAG, "bound device index:" + i + " device info:" + device.toString());
                    if (BluetoothUtil.isValidBleAddress(device.getDeviceAddress())) {
                        mSelectedBleDevices.add(device);
                    }
                }
            }
        }

        initActionBar();
        initView();
    }

    private void initActionBar() {
        ActionBar actionBar = getSupportActionBar();
        actionBar.setHomeButtonEnabled(true);
        setCenterTitle(getString(R.string.device_scanning));
        actionBar.setDisplayHomeAsUpEnabled(true);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.refresh,menu);
        mActionBar = menu;
        mActionBar.findItem(R.id.scan).setTitle(R.string.scanning);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // TODO Auto-generated method stub
        int id = item.getItemId();
        if (id == android.R.id.home) {
            finish();
            return true;
        } else if(id == R.id.scan) {
            if (mIsRefresing) {
                mIsRefresing = false;
                item.setTitle(R.string.scan);
                mSwipeRefreshLayout.setRefreshing(false);
                onPause();
            } else {
                mIsRefresing = true;
                item.setTitle(R.string.scanning);
                mSwipeRefreshLayout.setRefreshing(true);
                onResume();
            }
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mIsRefresing) {
            onRefresh();
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mIsRefresing) {
            mBleDeviceScanner.stopScan();
            mUsbDeviceScanner.stopScan();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mBleDeviceScanner.stopScan();
        mUsbDeviceScanner.stopScan();
    }

    private void initView() {
        mTvStart.setText(R.string.finish);
        mLeDeviceAdapter = new LeDevicesAdapter(mContext, mListBleDevices,
                mSelectedBleDevices, mIsSingleSelected);
        mListViewBleDevices.setAdapter(mLeDeviceAdapter);
        mSwipeRefreshLayout.setProgressViewOffset(false, 0,
                (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                        24, getResources().getDisplayMetrics()));
        mSwipeRefreshLayout.setOnRefreshListener(this);
    }

    @OnClick(R.id.rl_filter)
    public void OnFilterClicked(View v) {
        mPopWindow = new DeviceFilterPopWindow(LeDeviceListActivity.this, v);
        mPopWindow.show(mNameFilter, mAddressFilter, mMinRssi, new DeviceFilterPopWindow.Callback() {
            @Override
            public void onFilterChanged(String nameFilter, String advFilter, int rssi) {
                updateTvFilterValue(nameFilter, advFilter, rssi);
                mMinRssi = rssi;
                mNameFilter = nameFilter;
                mAddressFilter = advFilter;
                if (mMsgHandler.hasMessages(MSG_REFREH_DEVICE_SCAN_RESULT)) {
                    mMsgHandler.removeMessages(MSG_REFREH_DEVICE_SCAN_RESULT);
                    mMsgHandler.sendEmptyMessageDelayed(MSG_REFREH_DEVICE_SCAN_RESULT, 0);
                }
            }
        });
    }

    private void updateTvFilterValue(String nameFilter, String advFilter, int rssi) {
        StringBuilder sb = new StringBuilder();
        if (!nameFilter.isEmpty()) {
            sb.append(nameFilter);
        }

        if (!advFilter.isEmpty()) {
            if (!sb.toString().isEmpty()) {
                sb.append(",");
            }
            sb.append(advFilter);
        }

        if (rssi != 100) {
            if (!sb.toString().isEmpty()) {
                sb.append(",");
            }
            sb.append(",").append(String.valueOf(rssi));
        }

        mTvFilterInfo.setText(sb.toString());
    }

    @OnClick(R.id.img_delete)
    public void onBtnDeleteFilterClicked(View v) {
        if (null != mPopWindow) {
            mPopWindow.removeAllFilter();
        }
    }

    /**
     * 扫描BLE设备
     */
    private void scanBleDevices(IDeviceScanner deviceScanner) {
        deviceScanner.stopScan();
        deviceScanner.startScan(new Action1<RomaDevice>() {
                    @Override
                    public void call(RomaDevice device) {

                        BleDevicesInfo deviceAdv = BleDevicesInfo.create(device);
                        synchronized (mBuffer) {
                            mBuffer.put(deviceAdv.getDeviceAddress(), deviceAdv);
                        }

                        if (!mMsgHandler.hasMessages(MSG_REFREH_DEVICE_SCAN_RESULT)) {
                            mMsgHandler.sendEmptyMessageDelayed(MSG_REFREH_DEVICE_SCAN_RESULT, 2000);
                        }
                    }
                }, null);
    }


    Handler mMsgHandler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_REFREH_DEVICE_SCAN_RESULT:
                    synchronized (mBuffer) {
                        // update connected ble device
                        BleDevicesInfo device = null;
                        for (int i = 0; i < mBoundedDevices.size(); i++) {

                            device = mBoundedDevices.get(i);
                            if (BluetoothUtil.isValidBleAddress(device.getDeviceAddress())) {

                                Log.d(TAG, "add bound device:" + device.toString() + " into list");
                                mBuffer.put(device.getDeviceAddress(), device);
                            }
                        }

                        for (Map.Entry<String, BleDevicesInfo> entry : mBuffer.entrySet()) {
                            updateScanResult(entry.getValue());
                        }
                        mBuffer.clear();
                    }

                    sortDevice();
                    break;
            }
            return false;
        }
    });

    private void updateScanResult(BleDevicesInfo deviceInfo) {

        if (null == deviceInfo) {
            return;
        }

        int index = mListBleDevices.indexOf(deviceInfo);
        if (index >= 0) {
            mListBleDevices.get(index).setRSSI(deviceInfo.getRSSI());
        } else {
            mListBleDevices.add(deviceInfo);
        }
    }

    private void sortDevice() {
        Iterator<BleDevicesInfo> iter = mListBleDevices.iterator();
        while (iter.hasNext()) {
            BleDevicesInfo data = iter.next();
            if (data.getRSSI() < mMinRssi) {
                // rssi 过滤
                iter.remove();
            }else if (!data.getDeviceName().toUpperCase()
                    .contains(mNameFilter.toUpperCase())) {
                // 设备名过滤
                iter.remove();
            }else if (!data.getDeviceAddress().toUpperCase()
                    .contains(mAddressFilter.toUpperCase())) {
                // 地址过滤
                iter.remove();
            }
        }

        Collections.sort(mListBleDevices);
        notifyDataSetChanged();
    }

    @Override
    public void onRefresh() {
        if (mMsgHandler.hasMessages(MSG_REFREH_DEVICE_SCAN_RESULT)) {
            mMsgHandler.removeMessages(MSG_REFREH_DEVICE_SCAN_RESULT);
        }
        mListBleDevices.clear();
        notifyDataSetChanged();
        scanBleDevices(mBleDeviceScanner);
        scanBleDevices(mUsbDeviceScanner);
        scanSppDevice();
        if (null != mActionBar) {
            mActionBar.findItem(R.id.scan).setTitle(R.string.scanning);
        }
        mSwipeRefreshLayout.setRefreshing(true);
    }

    private void scanSppDevice() {
        List<RomaDevice> devicesInfoList = SppDeviceScanner.getConnectedBluetoothDevice();
        for (RomaDevice device : devicesInfoList) {
            mListBleDevices.add(new BleDevicesInfo(
                    device.getDeviceType(),
                    device.getDeviceName(),
                    device.getDeviceAddress(),
                    device.getRSSI(), ""));
        }
    }

    private void setSelectedBleDeviceResult() {
        Intent intent = new Intent();
        String jsonStr = new Gson().toJson(mSelectedBleDevices);
        intent.putExtra(SELECTED_BLE_DEVICES, jsonStr);
        setResult(RESULT_OK, intent);
    }

    @OnClick(R.id.tv_start)
    public void onBtnStartClicked() {

        if (mSelectedBleDevices.size() <= 1) {
            setSelectedBleDeviceResult();
            finish();
            return;
        }

        String[] items = new String[mSelectedBleDevices.size()];
        for (int i = 0; i < items.length; ++i) {
            items[i] = mSelectedBleDevices.get(i).getDeviceAddress();
        }

        AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
        builder.setTitle(getString(R.string.select_main_compare_device));
        builder.setItems(items, (dialogInterface, nPosition) -> {
            if (nPosition < mSelectedBleDevices.size()) {
                BleDevicesInfo devicesInfo = mSelectedBleDevices.get(0);
                mSelectedBleDevices.set(0, mSelectedBleDevices.get(nPosition));
                mSelectedBleDevices.set(nPosition, devicesInfo);
            }
            notifyDataSetChanged();
            setSelectedBleDeviceResult();
            finish();
        });
        builder.show();
    }

    private void notifyDataSetChanged() {
        mSwipeRefreshLayout.setRefreshing(false);
        mLeDeviceAdapter.notifyDataSetChanged();
    }
}
